home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / src / haeberli / libgutil / objfnt.c < prev    next >
C/C++ Source or Header  |  1994-08-01  |  36KB  |  1,770 lines

  1. /*
  2.  * Copyright 1991, 1992, 1993, 1994, Silicon Graphics, Inc.
  3.  * All Rights Reserved.
  4.  *
  5.  * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
  6.  * the contents of this file may not be disclosed to third parties, copied or
  7.  * duplicated in any form, in whole or in part, without the prior written
  8.  * permission of Silicon Graphics, Inc.
  9.  *
  10.  * RESTRICTED RIGHTS LEGEND:
  11.  * Use, duplication or disclosure by the Government is subject to restrictions
  12.  * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
  13.  * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
  14.  * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
  15.  * rights reserved under the Copyright Laws of the United States.
  16.  */
  17. /*
  18.  *    objfnt -     
  19.  *        Support for spline and polygonal fonts.
  20.  *
  21.  *                Paul Haeberli - 1990
  22.  */
  23. #include "stdio.h"
  24. #include "gl.h"
  25. #include "objfnt.h"
  26. #include "resource.h"
  27.  
  28. static poly_print();
  29. static spline_print();
  30. static drawcurve();
  31. static bezadapt();
  32.  
  33. /* the following characters are used by the SEAC command to make */
  34. /* accented (composite) characters in text fonts                 */
  35. pschar accentlist[NACCENT] = {
  36.     "/grave",           0301,   0,
  37.     "/acute",           0302,   0,
  38.     "/circumflex",      0303,   0,
  39.     "/tilde",           0304,   0,
  40.     "/macron",          0305,   0,
  41.     "/breve",           0306,   0,
  42.     "/dotaccent",       0307,   0,
  43.     "/dieresis",        0310,   0,
  44.     "/ring",            0312,   0,
  45.     "/cedilla",         0313,   0,
  46.     "/hungarumlaut",    0315,   0,
  47.     "/ogonek",          0316,   0,
  48.     "/caron",           0317,   0,
  49.     "/dotlessi",        0365,   0
  50. };
  51.  
  52. pschar charlist[NASCII] = {
  53.     "/space",         040,    0,
  54.     "/exclam",         041,    0,
  55.     "/quotedbl",     042,    0,
  56.     "/numbersign",     043,    0,
  57.     "/dollar",         044,    0,
  58.     "/percent",     045,    0,
  59.     "/ampersand",     046,    0,
  60.     "/quoteright",     047,    0,
  61.     "/parenleft",     050,    0,
  62.     "/parenright",     051,    0,
  63.     "/asterisk",     052,    0,
  64.     "/plus",         053,    0,
  65.     "/comma",         054,    0,
  66.     "/hyphen",         055,    0,
  67.     "/period",         056,    0,
  68.     "/slash",         057,    0,
  69.     "/zero",         060,    0,
  70.     "/one",         061,    0,
  71.     "/two",         062,    0,
  72.     "/three",         063,    0,
  73.     "/four",         064,    0,
  74.     "/five",         065,    0,
  75.     "/six",         066,    0,
  76.     "/seven",         067,    0,
  77.     "/eight",         070,    0,
  78.     "/nine",         071,    0,
  79.     "/colon",         072,    0,
  80.     "/semicolon",     073,    0,
  81.     "/less",         074,    0,
  82.     "/equal",         075,    0,
  83.     "/greater",         076,    0,
  84.     "/question",     077,    0,
  85.     "/at",         0100,    0,
  86.     "/A",         0101,    0,
  87.     "/B",         0102,    0,
  88.     "/C",         0103,    0,
  89.     "/D",         0104,    0,
  90.     "/E",         0105,    0,
  91.     "/F",         0106,    0,
  92.     "/G",         0107,    0,
  93.     "/H",         0110,    0,
  94.     "/I",         0111,    0,
  95.     "/J",         0112,    0,
  96.     "/K",         0113,    0,
  97.     "/L",         0114,    0,
  98.     "/M",         0115,    0,
  99.     "/N",         0116,    0,
  100.     "/O",         0117,    0,
  101.     "/P",         0120,    0,
  102.     "/Q",         0121,    0,
  103.     "/R",         0122,    0,
  104.     "/S",         0123,    0,
  105.     "/T",         0124,    0,
  106.     "/U",         0125,    0,
  107.     "/V",         0126,    0,
  108.     "/W",         0127,    0,
  109.     "/X",         0130,    0,
  110.     "/Y",         0131,    0,
  111.     "/Z",         0132,    0,
  112.     "/bracketleft",     0133,    0,
  113.     "/backslash",    0134,    0,
  114.     "/bracketright",     0135,    0,
  115.     "/asciicircum",    0136,    0,
  116.     "/underscore",     0137,    0,
  117.     "/quoteleft",     0140,    0,
  118.     "/a",         0141,    0,
  119.     "/b",         0142,    0,
  120.     "/c",         0143,    0,
  121.     "/d",        0144,    0,
  122.     "/e",         0145,    0,
  123.     "/f",        0146,    0,
  124.     "/g",         0147,    0,
  125.     "/h",         0150,    0,
  126.     "/i",         0151,    0,
  127.     "/j",         0152,    0,
  128.     "/k",         0153,    0,
  129.     "/l",        0154,    0,
  130.     "/m",         0155,    0,
  131.     "/n",        0156,    0,
  132.     "/o",         0157,    0,
  133.     "/p",         0160,    0,
  134.     "/q",         0161,    0,
  135.     "/r",         0162,    0,
  136.     "/s",         0163,    0,
  137.     "/t",        0164,    0,
  138.     "/u",        0165,    0,
  139.     "/v",         0166,    0,
  140.     "/w",        0167,    0,
  141.     "/x",         0170,    0,
  142.     "/y",         0171,    0,
  143.     "/z",         0172,    0,
  144.     "/braceleft",     0173,    0,
  145.     "/bar",        0174,    0,
  146.     "/braceright",    0175,    0,
  147.     "/asciitilde",     0176,    0,
  148.     NULL,        0177,    0,
  149.     NULL,        0200,    0,
  150.     NULL,        0201,    0,
  151.     NULL,        0202,    0,
  152.     NULL,        0203,    0,
  153.     NULL,        0204,    0,
  154.     NULL,        0205,    0,
  155.     NULL,        0206,    0,
  156.     NULL,        0207,    0,
  157.     NULL,        0210,    0,
  158.     NULL,        0211,    0,
  159.     NULL,        0212,    0,
  160.     NULL,        0213,    0,
  161.     NULL,        0214,    0,
  162.     NULL,        0215,    0,
  163.     NULL,        0216,    0,
  164.     NULL,        0217,    0,
  165.     NULL,        0220,    0,
  166.     NULL,        0221,    0,
  167.     NULL,        0222,    0,
  168.     NULL,        0223,    0,
  169.     NULL,        0224,    0,
  170.     NULL,        0225,    0,
  171.     NULL,        0226,    0,
  172.     NULL,        0227,    0,
  173.     NULL,        0230,    0,
  174.     NULL,        0231,    0,
  175.     NULL,        0232,    0,
  176.     NULL,        0233,    0,
  177.     NULL,        0234,    0,
  178.     NULL,        0235,    0,
  179.     NULL,        0236,    0,
  180.     NULL,        0237,    0,
  181.     NULL,        0240,    0,
  182.     "/exclamdown",     0241,    0,
  183.     "/cent",         0242,    0,
  184.     "/sterling",    0243,    0,
  185.     "/currency",    0244,    0,
  186.     "/yen",        0245,    0,
  187.     "/brokenbar",    0246,    0,
  188.     "/section",        0247,    0,
  189.     "/dieresis",    0250,    0,
  190.     "/copyright",    0251,    0,
  191.     "/ordfeminine",    0252,    0,
  192.     "/guillemotleft",    0253,    0,
  193.     "/logicalnot",    0254,    0,
  194.     "/hyphen",        0255,    0,
  195.     "/registered",    0256,    0,
  196.     "/macron",        0257,    0,
  197.     "/degree",        0260,    0,
  198.     "/plusminus",    0261,    0,
  199.     "/twosuperior",    0262,    0,
  200.     "/threesuperior",    0263,    0,
  201.     "/acute",        0264,    0,
  202.     "/mu",        0265,    0,
  203.     "/paragraph",    0266,    0,
  204.     "/periodcentered",    0267,    0,
  205.     "/cedilla",        0270,    0,
  206.     "/onesuperior",    0271,    0,
  207.     "/ordmasculine",    0272,    0,
  208.     "/guillemotright",    0273,    0,
  209.     "/onequarter",    0274,    0,
  210.     "/onehalf",        0275,    0,
  211.     "/threequarters",    0276,    0,
  212.     "/questiondown",    0277,    0,
  213.     "/Agrave",        0300,    0,
  214.     "/Aacute",        0301,    0,
  215.     "/Acircumflex",    0302,    0,
  216.     "/Atilde",        0303,    0,
  217.     "/Adieresis",    0304,    0,
  218.     "/Aring",        0305,    0,
  219.     "/AE",        0306,    0,
  220.     "/Ccedilla",    0307,    0,
  221.     "/Egrave",        0310,    0,
  222.     "/Eacute",        0311,    0,
  223.     "/Ecircumflex",    0312,    0,
  224.     "/Edieresis",    0313,    0,
  225.     "/Igrave",        0314,    0,
  226.     "/Iacute",        0315,    0,
  227.     "/Icircumflex",    0316,    0,
  228.     "/Idieresis",    0317,    0,
  229.     "/Eth",        0320,    0,
  230.     "/Ntilde",        0321,    0,
  231.     "/Ograve",        0322,    0,
  232.     "/Oacute",        0323,    0,
  233.     "/Ocircumflex",    0324,    0,
  234.     "/Otilde",        0325,    0,
  235.     "/Odieresis",    0326,    0,
  236.     "/multiply",    0327,    0,
  237.     "/Oslash",        0330,    0,
  238.     "/Ugrave",        0331,    0,
  239.     "/Uacute",        0332,    0,
  240.     "/Ucircumflex",    0333,    0,
  241.     "/Udieresis",    0334,    0,
  242.     "/Yacute",        0335,    0,
  243.     "/Thorn",        0336,    0,
  244.     "/germandbls",    0337,    0,
  245.     "/agrave",        0340,    0,
  246.     "/aacute",        0341,    0,
  247.     "/acircumflex",    0342,    0,
  248.     "/atilde",        0343,    0,
  249.     "/adieresis",    0344,    0,
  250.     "/aring",        0345,    0,
  251.     "/ae",        0346,    0,
  252.     "/ccedilla",    0347,    0,
  253.     "/egrave",        0350,    0,
  254.     "/eacute",        0351,    0,
  255.     "/ecircumflex",    0352,    0,
  256.     "/edieresis",    0353,    0,
  257.     "/igrave",        0354,    0,
  258.     "/iacute",        0355,    0,
  259.     "/icircumflex",    0356,    0,
  260.     "/idieresis",    0357,    0,
  261.     "/eth",        0360,    0,
  262.     "/ntilde",        0361,    0,
  263.     "/ograve",        0362,    0,
  264.     "/oacute",        0363,    0,
  265.     "/ocircumflex",    0364,    0,
  266.     "/otilde",        0365,    0,
  267.     "/odieresis",    0366,    0,
  268.     "/divide",        0367,    0,
  269.     "/oslash",        0370,    0,
  270.     "/ugrave",        0371,    0,
  271.     "/uacute",        0372,    0,
  272.     "/ucircumflex",    0373,    0,
  273.     "/udieresis",    0374,    0,
  274.     "/yacute",        0375,    0,
  275.     "/thorn",        0376,    0,
  276.     "/ydieresis",    0377,    0
  277. };
  278.  
  279. pschar scharlist[NSYMBL] = {
  280.     "/space",        040,    0,
  281.     "/exclam",        041,    0,
  282.     "/universal",    042,    0,
  283.     "/numbersign",    043,    0,
  284.     "/existential",    044,    0,
  285.     "/percent",        045,    0,
  286.     "/ampersand",    046,    0,
  287.     "/suchthat",    047,    0,
  288.     "/parenleft",    050,    0,
  289.     "/parenright",    051,    0,
  290.     "/asteriskmath",    052,    0,
  291.     "/plus",        053,    0,
  292.     "/comma",        054,    0,
  293.     "/minus",        055,    0,
  294.     "/period",        056,    0,
  295.     "/slash",        057,    0,
  296.     "/zero",        060,    0,
  297.     "/one",        061,    0,
  298.     "/two",        062,    0,
  299.     "/three",        063,    0,
  300.     "/four",        064,    0,
  301.     "/five",        065,    0,
  302.     "/six",        066,    0,
  303.     "/seven",        067,    0,
  304.     "/eight",        070,    0,
  305.     "/nine",        071,    0,
  306.     "/colon",        072,    0,
  307.     "/semicolon",    073,    0,
  308.     "/less",        074,    0,
  309.     "/equal",        075,    0,
  310.     "/greater",        076,    0,
  311.     "/question",    077,    0,
  312.     "/congruent",    0100,    0,
  313.     "/Alpha",        0101,    0,
  314.     "/Beta",        0102,    0,
  315.     "/Chi",        0103,    0,
  316.     "/Delta",        0104,    0,
  317.     "/Epsilon",        0105,    0,
  318.     "/Phi",        0106,    0,
  319.     "/Gamma",        0107,    0,
  320.     "/Eta",        0110,    0,
  321.     "/Iota",        0111,    0,
  322.     "/theta1",        0112,    0,
  323.     "/Kappa",        0113,    0,
  324.     "/Lambda",        0114,    0,
  325.     "/Mu",        0115,    0,
  326.     "/Nu",        0116,    0,
  327.     "/Omicron",        0117,    0,
  328.     "/Pi",        0120,    0,
  329.     "/Theta",        0121,    0,
  330.     "/Rho",        0122,    0,
  331.     "/Sigma",        0123,    0,
  332.     "/Tau",        0124,    0,
  333.     "/Upsilon",        0125,    0,
  334.     "/sigma1",        0126,    0,
  335.     "/Omega",        0127,    0,
  336.     "/Xi",        0130,    0,
  337.     "/Psi",        0131,    0,
  338.     "/Zeta",        0132,    0,
  339.     "/bracketleft",    0133,    0,
  340.     "/therefore",    0134,    0,
  341.     "/bracketright",    0135,    0,
  342.     "/perpendicular",    0136,    0,
  343.     "/underscore",    0137,    0,
  344.     "/radicalex",    0140,    0,
  345.     "/alpha",        0141,    0,
  346.     "/beta",        0142,    0,
  347.     "/chi",        0143,    0,
  348.     "/delta",        0144,    0,
  349.     "/epsilon",        0145,    0,
  350.     "/phi",        0146,    0,
  351.     "/gamma",        0147,    0,
  352.     "/eta",        0150,    0,
  353.     "/iota",        0151,    0,
  354.     "/phi1",        0152,    0,
  355.     "/kappa",        0153,    0,
  356.     "/lambda",        0154,    0,
  357.     "/mu",        0155,    0,
  358.     "/nu",        0156,    0,
  359.     "/omicron",        0157,    0,
  360.     "/pi",        0160,    0,
  361.     "/theta",        0161,    0,
  362.     "/rho",        0162,    0,
  363.     "/sigma",        0163,    0,
  364.     "/tau",        0164,    0,
  365.     "/upsilon",        0165,    0,
  366.     "/omega1",        0166,    0,
  367.     "/omega",        0167,    0,
  368.     "/xi",        0170,    0,
  369.     "/psi",        0171,    0,
  370.     "/zeta",        0172,    0,
  371.     "/braceleft",    0173,    0,
  372.     "/bar",        0174,    0,
  373.     "/braceright",    0175,    0,
  374.     "/similar",        0176,    0,
  375.     NULL,               0177,   0,
  376.     NULL,               0200,   0,
  377.     NULL,               0201,   0,
  378.     NULL,               0202,   0,
  379.     NULL,               0203,   0,
  380.     NULL,               0204,   0,
  381.     NULL,               0205,   0,
  382.     NULL,               0206,   0,
  383.     NULL,               0207,   0,
  384.     NULL,               0210,   0,
  385.     NULL,               0211,   0,
  386.     NULL,               0212,   0,
  387.     NULL,               0213,   0,
  388.     NULL,               0214,   0,
  389.     NULL,               0215,   0,
  390.     NULL,               0216,   0,
  391.     NULL,               0217,   0,
  392.     NULL,               0220,   0,
  393.     NULL,               0221,   0,
  394.     NULL,               0222,   0,
  395.     NULL,               0223,   0,
  396.     NULL,               0224,   0,
  397.     NULL,               0225,   0,
  398.     NULL,               0226,   0,
  399.     NULL,               0227,   0,
  400.     NULL,               0230,   0,
  401.     NULL,               0231,   0,
  402.     NULL,               0232,   0,
  403.     NULL,               0233,   0,
  404.     NULL,               0234,   0,
  405.     NULL,               0235,   0,
  406.     NULL,               0236,   0,
  407.     NULL,               0237,   0,
  408.     NULL,               0240,   0,
  409.     "/Upsilon1",    0241,    0,
  410.     "/minute",        0242,    0,
  411.     "/lessequal",    0243,    0,
  412.     "/fraction",    0244,    0,
  413.     "/infinity",    0245,    0,
  414.     "/florin",        0246,    0,
  415.     "/club",        0247,    0,
  416.     "/diamond",        0250,    0,
  417.     "/heart",        0251,    0,
  418.     "/spade",        0252,    0,
  419.     "/arrowboth",    0253,    0,
  420.     "/arrowleft",    0254,    0,
  421.     "/arrowup",        0255,    0,
  422.     "/arrowright",    0256,    0,
  423.     "/arrowdown",    0257,    0,
  424.     "/degree",        0260,    0,
  425.     "/plusminus",    0261,    0,
  426.     "/second",        0262,    0,
  427.     "/greaterequal",    0263,    0,
  428.     "/multiply",    0264,    0,
  429.     "/proportional",    0265,    0,
  430.     "/partialdiff",    0266,    0,
  431.     "/bullet",        0267,    0,
  432.     "/divide",        0270,    0,
  433.     "/notequal",    0271,    0,
  434.     "/equivalence",    0272,    0,
  435.     "/approxequal",    0273,    0,
  436.     "/ellipsis",    0274,    0,
  437.     "/arrowvertex",    0275,    0,
  438.     "/arrowhorizex",    0276,    0,
  439.     "/carriagereturn",    0277,    0,
  440.     "/aleph",        0300,    0,
  441.     "/Ifraktur",    0301,    0,
  442.     "/Rfraktur",    0302,    0,
  443.     "/weierstrass",    0303,    0,
  444.     "/circlemultiply",    0304,    0,
  445.     "/circleplus",    0305,    0,
  446.     "/emptyset",    0306,    0,
  447.     "/intersection",    0307,    0,
  448.     "/union",        0310,    0,
  449.     "/propersuperset",    0311,    0,
  450.     "/reflexsuperset",    0312,    0,
  451.     "/notsubset",    0313,    0,
  452.     "/propersubset",    0314,    0,
  453.     "/reflexsubset",    0315,    0,
  454.     "/element",        0316,    0,
  455.     "/notelement",    0317,    0,
  456.     "/angle",        0320,    0,
  457.     "/gradient",    0321,    0,
  458.     "/registerserif",    0322,    0,
  459.     "/copyrightserif",    0323,    0,
  460.     "/trademarkserif",    0324,    0,
  461.     "/product",        0325,    0,
  462.     "/radical",        0326,    0,
  463.     "/dotmath",        0327,    0,
  464.     "/logicalnot",    0330,    0,
  465.     "/logicaland",    0331,    0,
  466.     "/logicalor",    0332,    0,
  467.     "/arrowdblboth",    0333,    0,
  468.     "/arrowdblleft",    0334,    0,
  469.     "/arrowdblup",    0335,    0,
  470.     "/arrowdblright",    0336,    0,
  471.     "/arrowdbldown",    0337,    0,
  472.     "/lozenge",        0340,    0,
  473.     "/angleleft",    0341,    0,
  474.     "/registersans",    0342,    0,
  475.     "/copyrightsans",    0343,    0,
  476.     "/trademarksans",    0344,    0,
  477.     "/summation",    0345,    0,
  478.     "/parenlefttp",    0346,    0,
  479.     "/parenleftex",    0347,    0,
  480.     "/parenleftbt",    0350,    0,
  481.     "/bracketlefttp",    0351,    0,
  482.     "/bracketleftex",    0352,    0,
  483.     "/bracketleftbt",    0353,    0,
  484.     "/bracelefttp",    0354,    0,
  485.     "/braceleftmid",    0355,    0,
  486.     "/braceleftbt",    0356,    0,
  487.     "/braceex",        0357,    0,
  488.     "/apple",           0360,   0, 
  489.     "/angleright",    0361,    0,
  490.     "/integral",    0362,    0,
  491.     "/integraltp",    0363,    0,
  492.     "/integralex",    0364,    0,
  493.     "/integralbt",    0365,    0,
  494.     "/parenrighttp",    0366,    0,
  495.     "/parenrightex",    0367,    0,
  496.     "/parenrightbt",    0370,    0,
  497.     "/bracketrighttp",    0371,    0,
  498.     "/bracketrightex",    0372,    0,
  499.     "/bracketrightbt",    0373,    0,
  500.     "/bracerighttp",    0374,    0,
  501.     "/bracerightmid",    0375,    0,
  502.     "/bracerightbt",    0376,    0,
  503.     NULL,               0377,   0
  504. };
  505.  
  506. pschar zcharlist[NZAPFD] = {
  507.     "/space",        040,    0,
  508.     "/a1",        041,    0,
  509.     "/a2",        042,    0,
  510.     "/a202",        043,    0,
  511.     "/a3",        044,    0,
  512.     "/a4",        045,    0,
  513.     "/a5",        046,    0,
  514.     "/a119",        047,    0,
  515.     "/a118",        050,    0,
  516.     "/a117",        051,    0,
  517.     "/a11",        052,    0,
  518.     "/a12",        053,    0,
  519.     "/a13",        054,    0,
  520.     "/a14",        055,    0,
  521.     "/a15",        056,    0,
  522.     "/a16",        057,    0,
  523.     "/a105",        060,    0,
  524.     "/a17",        061,    0,
  525.     "/a18",        062,    0,
  526.     "/a19",        063,    0,
  527.     "/a20",        064,    0,
  528.     "/a21",        065,    0,
  529.     "/a22",        066,    0,
  530.     "/a23",        067,    0,
  531.     "/a24",        070,    0,
  532.     "/a25",        071,    0,
  533.     "/a26",        072,    0,
  534.     "/a27",        073,    0,
  535.     "/a28",        074,    0,
  536.     "/a6",        075,    0,
  537.     "/a7",        076,    0,
  538.     "/a8",        077,    0,
  539.     "/a9",        0100,    0,
  540.     "/a10",        0101,    0,
  541.     "/a29",        0102,    0,
  542.     "/a30",        0103,    0,
  543.     "/a31",        0104,    0,
  544.     "/a32",        0105,    0,
  545.     "/a33",        0106,    0,
  546.     "/a34",        0107,    0,
  547.     "/a35",        0110,    0,
  548.     "/a36",        0111,    0,
  549.     "/a37",        0112,    0,
  550.     "/a38",        0113,    0,
  551.     "/a39",        0114,    0,
  552.     "/a40",        0115,    0,
  553.     "/a41",        0116,    0,
  554.     "/a42",        0117,    0,
  555.     "/a43",        0120,    0,
  556.     "/a44",        0121,    0,
  557.     "/a45",        0122,    0,
  558.     "/a46",        0123,    0,
  559.     "/a47",        0124,    0,
  560.     "/a48",        0125,    0,
  561.     "/a49",        0126,    0,
  562.     "/a50",        0127,    0,
  563.     "/a51",        0130,    0,
  564.     "/a52",        0131,    0,
  565.     "/a53",        0132,    0,
  566.     "/a54",        0133,    0,
  567.     "/a55",        0134,    0,
  568.     "/a56",        0135,    0,
  569.     "/a57",        0136,    0,
  570.     "/a58",        0137,    0,
  571.     "/a59",        0140,    0,
  572.     "/a60",        0141,    0,
  573.     "/a61",        0142,    0,
  574.     "/a62",        0143,    0,
  575.     "/a63",        0144,    0,
  576.     "/a64",        0145,    0,
  577.     "/a65",        0146,    0,
  578.     "/a66",        0147,    0,
  579.     "/a67",        0150,    0,
  580.     "/a68",        0151,    0,
  581.     "/a69",        0152,    0,
  582.     "/a70",        0153,    0,
  583.     "/a71",        0154,    0,    
  584.     "/a72",        0155,    0,
  585.     "/a73",        0156,    0,
  586.     "/a74",        0157,    0,
  587.     "/a203",        0160,    0,
  588.     "/a75",        0161,    0,
  589.     "/a204",        0162,    0,
  590.     "/a76",        0163,    0,
  591.     "/a77",        0164,    0,
  592.     "/a78",        0165,    0,
  593.     "/a79",        0166,    0,
  594.     "/a81",        0167,    0,
  595.     "/a82",        0170,    0,
  596.     "/a83",        0171,    0,
  597.     "/a84",        0172,    0,
  598.     "/a97",        0173,    0,
  599.     "/a98",        0174,    0,
  600.     "/a99",        0175,    0,
  601.     "/a100",        0176,    0,
  602.     NULL,               0177,   0,
  603.     NULL,               0200,   0,
  604.     NULL,               0201,   0,
  605.     NULL,               0202,   0,
  606.     NULL,               0203,   0,
  607.     NULL,               0204,   0,
  608.     NULL,               0205,   0,
  609.     NULL,               0206,   0,
  610.     NULL,               0207,   0,
  611.     NULL,               0210,   0,
  612.     NULL,               0211,   0,
  613.     NULL,               0212,   0,
  614.     NULL,               0213,   0,
  615.     NULL,               0214,   0,
  616.     NULL,               0215,   0,
  617.     NULL,               0216,   0,
  618.     NULL,               0217,   0,
  619.     NULL,               0220,   0,
  620.     NULL,               0221,   0,
  621.     NULL,               0222,   0,
  622.     NULL,               0223,   0,
  623.     NULL,               0224,   0,
  624.     NULL,               0225,   0,
  625.     NULL,               0226,   0,
  626.     NULL,               0227,   0,
  627.     NULL,               0230,   0,
  628.     NULL,               0231,   0,
  629.     NULL,               0232,   0,
  630.     NULL,               0233,   0,
  631.     NULL,               0234,   0,
  632.     NULL,               0235,   0,
  633.     NULL,               0236,   0,
  634.     NULL,               0237,   0,
  635.     NULL,               0240,   0,
  636.     "/a101",        0241,    0,
  637.     "/a102",        0242,    0,
  638.     "/a103",        0243,    0,
  639.     "/a104",        0244,    0,
  640.     "/a106",        0245,    0,
  641.     "/a107",        0246,    0,
  642.     "/a108",        0247,    0,
  643.     "/a112",        0250,    0,
  644.     "/a111",        0251,    0,
  645.     "/a110",        0252,    0,
  646.     "/a109",        0253,    0,
  647.     "/a120",        0254,    0,
  648.     "/a121",        0255,    0,
  649.     "/a122",        0256,    0,
  650.     "/a123",        0257,    0,
  651.     "/a124",        0260,    0,
  652.     "/a125",        0261,    0,
  653.     "/a126",        0262,    0,
  654.     "/a127",        0263,    0,
  655.     "/a128",        0264,    0,
  656.     "/a129",        0265,    0,
  657.     "/a130",        0266,    0,
  658.     "/a131",        0267,    0,
  659.     "/a132",        0270,    0,
  660.     "/a133",        0271,    0,
  661.     "/a134",        0272,    0,
  662.     "/a135",        0273,    0,
  663.     "/a136",        0274,    0,
  664.     "/a137",        0275,    0,
  665.     "/a138",        0276,    0,
  666.     "/a139",        0277,    0,
  667.     "/a140",        0300,    0,
  668.     "/a141",        0301,    0,
  669.     "/a142",        0302,    0,
  670.     "/a143",        0303,    0,
  671.     "/a144",        0304,    0,
  672.     "/a145",        0305,    0,
  673.     "/a146",        0306,    0,
  674.     "/a147",        0307,    0,
  675.     "/a148",        0310,    0,
  676.     "/a149",        0311,    0,
  677.     "/a150",        0312,    0,
  678.     "/a151",        0313,    0,
  679.     "/a152",        0314,    0,
  680.     "/a153",        0315,    0,
  681.     "/a154",        0316,    0,
  682.     "/a155",        0317,    0,
  683.     "/a156",        0320,    0,
  684.     "/a157",        0321,    0,
  685.     "/a158",        0322,    0,
  686.     "/a159",        0323,    0,
  687.     "/a160",        0324,    0,
  688.     "/a161",        0325,    0,
  689.     "/a163",        0326,    0,
  690.     "/a164",        0327,    0,
  691.     "/a196",        0330,    0,
  692.     "/a165",        0331,    0,
  693.     "/a192",        0332,    0,
  694.     "/a166",        0333,    0,
  695.     "/a167",        0334,    0,
  696.     "/a168",        0335,    0,
  697.     "/a169",        0336,    0,
  698.     "/a170",        0337,    0,
  699.     "/a171",        0340,    0,
  700.     "/a172",        0341,    0,
  701.     "/a173",        0342,    0,
  702.     "/a162",        0343,    0,
  703.     "/a174",        0344,    0,
  704.     "/a175",        0345,    0,
  705.     "/a176",        0346,    0,
  706.     "/a177",        0347,    0,
  707.     "/a178",        0350,    0,
  708.     "/a179",        0351,    0,
  709.     "/a193",        0352,    0,
  710.     "/a180",        0353,    0,
  711.     "/a199",        0354,    0,
  712.     "/a181",        0355,    0,
  713.     "/a200",        0356,    0,
  714.     "/a182",        0357,    0,
  715.     NULL,               0360,   0,
  716.     "/a201",        0361,    0,
  717.     "/a183",        0362,    0,
  718.     "/a184",        0363,    0,
  719.     "/a197",        0364,    0,
  720.     "/a185",        0365,    0,
  721.     "/a194",        0366,    0,
  722.     "/a198",        0367,    0,
  723.     "/a186",        0370,    0,
  724.     "/a195",        0371,    0,
  725.     "/a187",        0372,    0,
  726.     "/a188",        0373,    0,
  727.     "/a189",        0374,    0,
  728.     "/a190",        0375,    0,
  729.     "/a191",        0376,    0,
  730.     NULL,               0377,   0
  731. };
  732.  
  733. static int dopoints;
  734.  
  735. fntpointmode(size)
  736. int size;
  737. {
  738.     dopoints = size;
  739. }
  740.  
  741. /*
  742.  *    printing stuff for debugging
  743.  *
  744.  *
  745.  */
  746. printobjfnt(fnt)
  747. objfnt *fnt;
  748. {
  749.     int i;
  750.  
  751.     printf("Object font type is %d\n",fnt->type);
  752.     printf("First char is %d\n",fnt->charmin);
  753.     printf("Last char is %d\n",fnt->charmax);
  754.     printf("Num chars is %d\n",fnt->nchars);
  755.     printf("Fnt scale is %d\n\n",fnt->scale);
  756.     for(i=fnt->charmin; i<=fnt->charmax; i++) 
  757.     printobjchar(fnt,i);
  758. }
  759.  
  760. short *getcharprog(fnt,c)
  761. objfnt *fnt;
  762. int c;
  763. {
  764.     int index;
  765.     chardesc *cd;
  766.  
  767.     index = chartoindex(fnt,c);
  768.     if(index<0)
  769.     return 0;
  770.     cd = fnt->chars+index;
  771.     return cd->data;
  772. }
  773.  
  774. chardesc *getchardesc(fnt,c)
  775. objfnt *fnt;
  776. int c;
  777. {
  778.     int index;
  779.  
  780.     index = chartoindex(fnt,c);
  781.     if(index<0)
  782.     return 0;
  783.     return fnt->chars+index;
  784. }
  785.  
  786. int chartoindex(fnt,c)
  787. objfnt *fnt;
  788. int c;
  789. {
  790.     if(c<fnt->charmin)
  791.     return -1;
  792.     if(c>fnt->charmax)
  793.     return -1;
  794.     return c-fnt->charmin;
  795. }
  796.  
  797. printobjchar(fnt,c)
  798. objfnt *fnt;
  799. int c;
  800. {
  801.     int index;
  802.     chardesc *cd;
  803.  
  804.     index = chartoindex(fnt,c);
  805.     if(index<0)
  806.     return 0;
  807.     cd = fnt->chars+index;
  808.     printf("Char '%c' code is %d\n",c,c);
  809.     printf("Advance %d %d\n",cd->movex,cd->movey);
  810.     printf("Bbox %d %d to %d %d\n",cd->llx,cd->lly,cd->urx,cd->ury);
  811.     printf("Data %d tokens\n\n",cd->datalen/2);
  812.     if(cd->data) {
  813.     switch(fnt->type) {
  814.         case PO_TYPE:
  815.         poly_print(cd->data);
  816.         break;
  817.         case SP_TYPE:
  818.         spline_print(cd->data);
  819.         break;
  820.         case TM_TYPE:
  821.         fprintf(stderr,"printobjchar: can't print meshed fonts yet\n");
  822.         break;
  823.         default:
  824.         fprintf(stderr,"printobjchar: bad obj font type\n");
  825.     }
  826.     }
  827.     return 1;
  828. }
  829.  
  830. applytoobjfntverts(fnt,func)
  831. objfnt *fnt;
  832. int (*func)();
  833. {
  834.     int c;
  835.  
  836.     for(c=fnt->charmin; c<=fnt->charmax; c++) 
  837.     applytocharverts(fnt,c,func);
  838. }
  839.  
  840. applytocharverts(fnt,c,func)
  841. objfnt *fnt;
  842. int c;
  843. int (*func)();
  844. {
  845.     int index;
  846.     chardesc *cd;
  847.     short *sptr;
  848.     int nverts;
  849.  
  850.     index = chartoindex(fnt,c);
  851.     if(index<0)
  852.     return;
  853.     cd = fnt->chars+index;
  854.     if(cd->data) {
  855.     sptr = cd->data;
  856.     switch(fnt->type) {
  857.         case TM_TYPE:
  858.         while(1) {
  859.             switch(*sptr++) {    
  860.             case TM_BGNTMESH:
  861.             case TM_SWAPTMESH:
  862.             case TM_ENDBGNTMESH:
  863.                 break;
  864.             case TM_RETENDTMESH:
  865.             case TM_RET:
  866.                 return;
  867.             default:
  868.                 fprintf(stderr,"applytocharverts: bad TM op\n");
  869.                 return;
  870.             }
  871.             nverts = *sptr++;
  872.             while(nverts--) {
  873.             (func)(sptr);
  874.             sptr+=2;
  875.             }
  876.         }
  877.         break;
  878.         case PO_TYPE:
  879.         while(1) {
  880.             switch(*sptr++) {    
  881.             case PO_BGNLOOP:
  882.             case PO_ENDBGNLOOP:
  883.                 break;
  884.             case PO_RETENDLOOP:
  885.             case PO_RET:
  886.                 return;
  887.                 break;
  888.             default:
  889.                 fprintf(stderr,"applytocharverts: bad PO op\n");
  890.                 return;
  891.             }
  892.             nverts = *sptr++;
  893.             while(nverts--) {
  894.             (func)(sptr);
  895.             sptr+=2;
  896.             }
  897.         }
  898.         break;
  899.         case SP_TYPE:
  900.         while(1) {
  901.             switch(*sptr++) {    
  902.             case SP_MOVETO:
  903.                 (func)(sptr);
  904.                 sptr+=2;
  905.                 break;
  906.             case SP_LINETO:
  907.                 (func)(sptr);
  908.                 sptr+=2;
  909.                 break;
  910.             case SP_CURVETO:
  911.                 (func)(sptr+0);
  912.                 (func)(sptr+2);
  913.                 (func)(sptr+4);
  914.                 sptr+=6;
  915.                 break;
  916.             case SP_CLOSEPATH:
  917.                 break;
  918.             case SP_RETCLOSEPATH:
  919.                 return;
  920.                 break;
  921.             case SP_RET:
  922.                 return;
  923.                 break;
  924.             default:
  925.                 fprintf(stderr,"applytocharverts: bad SP op\n");
  926.                 return;
  927.             }
  928.         }
  929.         break;
  930.         default:
  931.         fprintf(stderr,"applytocharverts: bad obj font type\n");
  932.     }
  933.     }
  934. }
  935.  
  936. applytocharedges(fnt,c,func)
  937. objfnt *fnt;
  938. int c;
  939. int (*func)();
  940. {
  941.     int i, index, nverts;
  942.     chardesc *cd;
  943.     short *sptr, *p1, *p2;
  944.  
  945.     if(fnt->type != PO_TYPE) {
  946.         fprintf(stderr,"applytocharedges only works on PO_TYPE fonts\n");
  947.         exit(1);
  948.     }
  949.     index = chartoindex(fnt,c);
  950.     if(index<0)
  951.         return;
  952.     cd = fnt->chars+index;
  953.     if(cd->data) {
  954.         sptr = cd->data;
  955.         while(1) {
  956.             switch(*sptr++) {
  957.                 case PO_BGNLOOP:
  958.                 case PO_ENDBGNLOOP:
  959.                     break;
  960.                 case PO_RETENDLOOP:
  961.                 case PO_RET:
  962.                     return;
  963.             }
  964.             nverts = *sptr++;
  965.             for(i=0; i<nverts; i++) {
  966.                 p1 = sptr+(2*(i));
  967.                 p2 = sptr+(2*((i+1)%nverts));
  968.                 (func)(p1,p2);
  969.             }
  970.             sptr+=(2*nverts);
  971.         }
  972.     }
  973. }
  974.  
  975. static int xmin, xmax, ymin, ymax;
  976.  
  977. static bboxcalc(v)
  978. short v[2];
  979. {
  980.     if(v[0]<xmin)
  981.     xmin = v[0];
  982.     if(v[1]<ymin)
  983.     ymin = v[1];
  984.     if(v[0]>xmax)
  985.     xmax = v[0];
  986.     if(v[1]>ymax)
  987.     ymax = v[1];
  988. }
  989.  
  990. fontbbox(fnt,llx,lly,urx,ury)
  991. objfnt *fnt;
  992. int *llx, *lly, *urx, *ury;
  993. {
  994.     xmin = ymin = NOBBOX;
  995.     xmax = ymax = -NOBBOX;
  996.     applytoobjfntverts(fnt,bboxcalc);
  997.     if(xmin == NOBBOX) {
  998.     *llx = NOBBOX;
  999.     *lly = NOBBOX;
  1000.     *urx = NOBBOX;
  1001.     *ury = NOBBOX;
  1002.     } else {
  1003.     *llx = xmin;
  1004.     *lly = ymin;
  1005.     *urx = xmax;
  1006.     *ury = ymax;
  1007.     }
  1008. }
  1009.  
  1010. calccharbboxes(fnt)
  1011. objfnt *fnt;
  1012. {
  1013.     int c;
  1014.     chardesc *cd;
  1015.  
  1016.     for(c=fnt->charmin; c<=fnt->charmax; c++) {
  1017.     xmin = ymin = NOBBOX;
  1018.     xmax = ymax = -NOBBOX;
  1019.     applytocharverts(fnt,c,bboxcalc);
  1020.     cd = getchardesc(fnt,c);
  1021.     if(xmin == NOBBOX) {
  1022.         cd->llx = NOBBOX;
  1023.         cd->lly = NOBBOX;
  1024.         cd->urx = NOBBOX;
  1025.         cd->ury = NOBBOX;
  1026.     } else {
  1027.         cd->llx = xmin;
  1028.         cd->lly = ymin;
  1029.         cd->urx = xmax;
  1030.         cd->ury = ymax;
  1031.     }
  1032.     }
  1033. }
  1034.  
  1035.  
  1036. /*
  1037.  *    poly_print -
  1038.  *        Print a poly character
  1039.  *
  1040.  */
  1041. static poly_print(sptr)
  1042. short *sptr;
  1043. {
  1044.     int nverts;
  1045.  
  1046.     while(1) {
  1047.     switch(*sptr++) {    
  1048.         case PO_BGNLOOP:
  1049.         printf("bgnloop\n");
  1050.         break;
  1051.         case PO_ENDBGNLOOP:
  1052.         printf("endbgnloop\n\n");
  1053.         break;
  1054.         case PO_RETENDLOOP:
  1055.         printf("retendloop\n\n");
  1056.         return;
  1057.         break;
  1058.         case PO_RET:
  1059.         printf("ret\n\n");
  1060.         return;
  1061.         break;
  1062.         default:
  1063.         fprintf(stderr,"poly_print: bad PO op\n");
  1064.         return;
  1065.     }
  1066.         nverts = *sptr++;
  1067.     while(nverts--) {
  1068.         printf("    vert %d %d\n",sptr[0],sptr[1]);
  1069.         sptr+=2;
  1070.     }
  1071.     }
  1072. }
  1073.  
  1074.  
  1075. /*
  1076.  *    spline_print -
  1077.  *        Print a spline character
  1078.  *
  1079.  */
  1080. static spline_print(sptr)
  1081. short *sptr;
  1082. {
  1083.     int nverts;
  1084.  
  1085.     while(1) {
  1086.     switch(*sptr++) {    
  1087.         case SP_MOVETO:
  1088.         printf("beginloop\n");
  1089.         printf("    moveto %d %d\n",sptr[0], sptr[1]);
  1090.         sptr+=2;
  1091.         break;
  1092.         case SP_LINETO:
  1093.         printf("    lineto %d %d\n",sptr[0], sptr[1]);
  1094.         sptr+=2;
  1095.         break;
  1096.         case SP_CURVETO:
  1097.         printf("    curveto %d %d %d %d %d %d\n",
  1098.             sptr[0],sptr[1],sptr[2],sptr[3],sptr[4],sptr[5]);
  1099.         sptr+=6;
  1100.         break;
  1101.         case SP_CLOSEPATH:
  1102.         printf("endloop\n");
  1103.         break;
  1104.         case SP_RETCLOSEPATH:
  1105.         printf("endloop\n");
  1106.         printf("ret\n\n");
  1107.         return;
  1108.         break;
  1109.         case SP_RET:
  1110.         printf("ret\n\n");
  1111.         return;
  1112.         break;
  1113.         default:
  1114.         fprintf(stderr,"spline_print: bad SP op\n");
  1115.         return;
  1116.     }
  1117.     }
  1118. }
  1119.  
  1120.  
  1121. /*
  1122.  *    tmesh_draw -
  1123.  *        Draw a tmesh character
  1124.  *
  1125.  */
  1126. static tmesh_draw(sptr)
  1127. short *sptr;
  1128. {
  1129.     int nverts;
  1130.  
  1131.     while(1) {
  1132.     switch(*sptr++) {    
  1133.         case TM_BGNTMESH:
  1134.         bgntmesh();
  1135.         break;
  1136.         case TM_SWAPTMESH:
  1137.         swaptmesh();
  1138.         break;
  1139.         case TM_ENDBGNTMESH:
  1140.         endtmesh();
  1141.         bgntmesh();
  1142.         break;
  1143.         case TM_RETENDTMESH:
  1144.         endtmesh();
  1145.         return;
  1146.         case TM_RET:
  1147.         endtmesh();
  1148.         return;
  1149.         default:
  1150.         fprintf(stderr,"tmesh_draw: bad TM op\n");
  1151.         return;
  1152.     }
  1153.     nverts = *sptr++;
  1154.     while(nverts--) {
  1155.         v2s(sptr);
  1156.         sptr+=2;
  1157.     }
  1158.     }
  1159. }
  1160.  
  1161. /*
  1162.  *    point_draw -
  1163.  *        Draw the points in a character.
  1164.  *
  1165.  */
  1166. static point_draw(sptr,size)
  1167. short *sptr;
  1168. int size;
  1169. {
  1170.     int nverts, vertno;
  1171.     int x, y, del;
  1172.  
  1173.     del = size/2;
  1174.     if(del == 0)
  1175.     del = 1;
  1176.     while(1) {
  1177.     switch(*sptr++) {    
  1178.         case PO_BGNLOOP:
  1179.         break;
  1180.         case PO_ENDBGNLOOP:
  1181.         break;
  1182.         case PO_RETENDLOOP:
  1183.         return;
  1184.         break;
  1185.         case PO_RET:
  1186.         return;
  1187.         break;
  1188.         default:
  1189.         fprintf(stderr,"point_draw: bad PO op\n");
  1190.         return;
  1191.     }
  1192.         nverts = *sptr++;
  1193.      vertno = 1;
  1194.     while(nverts--) {
  1195.         x = sptr[0];
  1196.         y = sptr[1];
  1197.         if(vertno++ == 1)
  1198.         cpack(0x008000);
  1199.         else
  1200.         cpack(0x0000ff);
  1201.         if(size == 1)
  1202.         pnt2i(x,y);
  1203.         else
  1204.         rectfi(x-del,y-del,x+del,y+del);
  1205.         sptr+=2;
  1206.     }
  1207.     }
  1208. }
  1209.  
  1210. /*
  1211.  *    poly_draw -
  1212.  *        Draw a poly character
  1213.  *
  1214.  */
  1215. static poly_draw(sptr)
  1216. short *sptr;
  1217. {
  1218.     int nverts;
  1219.  
  1220.     while(1) {
  1221.     switch(*sptr++) {    
  1222.         case PO_BGNLOOP:
  1223.         bgnclosedline();
  1224.         break;
  1225.         case PO_ENDBGNLOOP:
  1226.         endclosedline();
  1227.         bgnclosedline();
  1228.         break;
  1229.         case PO_RETENDLOOP:
  1230.         endclosedline();
  1231.         return;
  1232.         break;
  1233.         case PO_RET:
  1234.         return;
  1235.         break;
  1236.         default:
  1237.         fprintf(stderr,"poly_draw: bad PO op\n");
  1238.         return;
  1239.     }
  1240.         nverts = *sptr++;
  1241.     while(nverts--) {
  1242.         v2s(sptr);
  1243.         sptr+=2;
  1244.     }
  1245.     }
  1246. }
  1247.  
  1248. /*
  1249.  *    spline_draw -
  1250.  *        Draw a spline character
  1251.  *
  1252.  */
  1253. static spline_draw(sptr)
  1254. short *sptr;
  1255. {
  1256.     while(1) {
  1257.     switch(*sptr++) {    
  1258.         case SP_MOVETO:
  1259.         bgnclosedline();
  1260.         v2s(sptr);
  1261.         sptr+=2;
  1262.         break;
  1263.         case SP_LINETO:
  1264.         v2s(sptr);
  1265.         sptr+=2;
  1266.         break;
  1267.         case SP_CURVETO:
  1268.         drawcurve(sptr-3,sptr,sptr+2,sptr+4);
  1269.         sptr+=6;
  1270.         break;
  1271.         case SP_CLOSEPATH:
  1272.         endclosedline();
  1273.         break;
  1274.         case SP_RETCLOSEPATH:
  1275.         endclosedline();
  1276.         return;
  1277.         break;
  1278.         case SP_RET:
  1279.         return;
  1280.         break;
  1281.         default:
  1282.         fprintf(stderr,"spline_draw: bad SP op\n");
  1283.         return;
  1284.     }
  1285.     }
  1286. }
  1287.  
  1288. #define BEZTOL    2.0
  1289.  
  1290. static drawcurve(v0,v1,v2,v3)
  1291. short v0[2], v1[2], v2[2], v3[2];
  1292. {
  1293.     float x0, y0, x1, y1, x2, y2, x3, y3;
  1294.  
  1295.     x0 = v0[0];
  1296.     y0 = v0[1];
  1297.     x1 = v1[0];
  1298.     y1 = v1[1];
  1299.     x2 = v2[0];
  1300.     y2 = v2[1];
  1301.     x3 = v3[0];
  1302.     y3 = v3[1];
  1303.     bezadapt(x0,y0,x1,y1,x2,y2,x3,y3,BEZTOL);
  1304. }
  1305.  
  1306. static bezadapt(x0,y0,x1,y1,x2,y2,x3,y3,beztol)
  1307. float x0,y0,x1,y1,x2,y2,x3,y3;
  1308. float beztol;
  1309. {
  1310.     float ax0,ay0,ax1,ay1,ax2,ay2,ax3,ay3;
  1311.     float bx0,by0,bx1,by1,bx2,by2,bx3,by3;
  1312.     float midx, midy;
  1313.     float linx, liny, dx, dy, mag;
  1314.     float v[2];
  1315.    
  1316.     midx = (x0+3*x1+3*x2+x3)/8.0;
  1317.     midy = (y0+3*y1+3*y2+y3)/8.0;
  1318.     linx = (x0+x3)/2.0;
  1319.     liny = (y0+y3)/2.0;
  1320.     dx = midx-linx;
  1321.     dy = midy-liny;
  1322.     mag = dx*dx+dy*dy;
  1323.     if(mag<(beztol*beztol)) {
  1324.     v[0] = x3;
  1325.     v[1] = y3;
  1326.     v2f(v);
  1327.     } else {
  1328.     ax0 = x0;
  1329.     ay0 = y0;
  1330.     ax1 = (x0+x1)/2;
  1331.     ay1 = (y0+y1)/2;
  1332.     ax2 = (x0+2*x1+x2)/4;
  1333.     ay2 = (y0+2*y1+y2)/4;
  1334.     ax3 = midx;
  1335.     ay3 = midy;
  1336.     bezadapt(ax0,ay0,ax1,ay1,ax2,ay2,ax3,ay3,beztol);
  1337.  
  1338.     bx0 = midx;
  1339.     by0 = midy;
  1340.     bx1 = (x1+2*x2+x3)/4;
  1341.     by1 = (y1+2*y2+y3)/4;
  1342.     bx2 = (x2+x3)/2;
  1343.     by2 = (y2+y3)/2;
  1344.     bx3 = x3;
  1345.     by3 = y3;
  1346.     bezadapt(bx0,by0,bx1,by1,bx2,by2,bx3,by3,beztol);
  1347.     }
  1348. }
  1349.  
  1350. objfnt *readobjfnt(name)
  1351. char *name;
  1352. {
  1353.     FILE *inf;
  1354.     objfnt *fnt;
  1355.     short *sptr;
  1356.     int i;
  1357.     long magic;
  1358.  
  1359.     inf = res_fopen(name,"r");
  1360.     if(!inf) {
  1361.     fprintf(stderr,"readobjfnt: can't open input file %s\n",name);
  1362.     return 0;
  1363.     }
  1364.     res_fread(&magic,sizeof(long),1,inf);
  1365.     if(magic != OFMAGIC) {
  1366.     fprintf(stderr,"readobjfnt: bad magic nuber\n");
  1367.     return 0;
  1368.     }
  1369.     fnt = (objfnt *)mymalloc(sizeof(objfnt));
  1370.     res_fread(fnt,sizeof(objfnt),1,inf);
  1371.     fnt->freeaddr = 0;
  1372.     fnt->chars = (chardesc *)mymalloc(fnt->nchars*sizeof(chardesc));
  1373.     res_fread(fnt->chars,fnt->nchars*sizeof(chardesc),1,inf);
  1374.     for(i=0; i<fnt->nchars; i++) {
  1375.     if(fnt->chars[i].datalen>0) {
  1376.         sptr = (short *)mymalloc(fnt->chars[i].datalen);
  1377.         fnt->chars[i].data = sptr;
  1378.         fread(sptr,fnt->chars[i].datalen,1,inf);
  1379.     } else {
  1380.         fnt->chars[i].data = 0;
  1381.     }
  1382.     }
  1383.     res_fclose(inf);
  1384.     return fnt;
  1385. }
  1386.  
  1387. writeobjfnt(name,fnt)
  1388. char *name;
  1389. objfnt *fnt;
  1390. {
  1391.     FILE *of;
  1392.     int i;
  1393.     long magic;
  1394.  
  1395.     calccharbboxes(fnt);
  1396.     of = fopen(name,"w");
  1397.     if(!of) {
  1398.     fprintf(stderr,"writeobjfnt: can't open output file %s\n",name);
  1399.     return 0;
  1400.     }
  1401.     magic = OFMAGIC;
  1402.     fwrite(&magic,sizeof(long),1,of);
  1403.     fwrite(fnt,sizeof(objfnt),1,of);
  1404.     fwrite(fnt->chars,fnt->nchars*sizeof(chardesc),1,of);
  1405.     for(i=0; i<fnt->nchars; i++) {
  1406.     if(fnt->chars[i].datalen>0) 
  1407.         fwrite(fnt->chars[i].data,fnt->chars[i].datalen,1,of);
  1408.     }
  1409.     fclose(of);
  1410. }
  1411.  
  1412. objfnt *newobjfnt(type,charmin,charmax,fscale)
  1413. int type, charmin, charmax, fscale;
  1414. {
  1415.     objfnt *fnt;
  1416.     short *sptr;
  1417.     int i;
  1418.  
  1419.     fnt = (objfnt *)mymalloc(sizeof(objfnt));
  1420.     fnt->freeaddr = 0;
  1421.     fnt->type = type;
  1422.     fnt->charmin = charmin;
  1423.     fnt->charmax = charmax;
  1424.     fnt->nchars = fnt->charmax-fnt->charmin+1;
  1425.     fnt->scale = fscale;
  1426.     fnt->chars = (chardesc *)mymalloc(fnt->nchars*sizeof(chardesc));
  1427.     bzero(fnt->chars,fnt->nchars*sizeof(chardesc));
  1428.     return fnt;
  1429. }
  1430.  
  1431. freeobjfnt(fnt)
  1432. objfnt *fnt;
  1433. {
  1434.     int i;
  1435.     chardesc *cd;
  1436.  
  1437.     cd = fnt->chars;
  1438.     for(i=0; i<fnt->nchars; i++) {
  1439.     if(cd->data)
  1440.         free(cd->data);
  1441.     cd++;
  1442.     }
  1443.     free(fnt->chars);
  1444.     free(fnt);
  1445. }
  1446.  
  1447. addchardata(fnt,c,data,nshorts)
  1448. objfnt *fnt;
  1449. int c;
  1450. short *data;
  1451. int nshorts;
  1452. {
  1453.     int index;
  1454.     chardesc *cd;
  1455.  
  1456.     index = chartoindex(fnt,c);
  1457.     if(index<0) {
  1458.     fprintf(stderr,"Addchardata bad poop\n");
  1459.     return;
  1460.     }
  1461.     cd = fnt->chars+index;
  1462.     fnt->freeaddr = 0;
  1463.     cd->datalen = nshorts*sizeof(short);
  1464.     cd->data = (short *)mymalloc(cd->datalen);
  1465.     bcopy(data,cd->data,cd->datalen);
  1466. }
  1467.  
  1468. addcharmetrics(fnt,c,movex,movey)
  1469. objfnt *fnt;
  1470. int c;
  1471. int movex, movey;
  1472. {
  1473.     int index;
  1474.     chardesc *cd;
  1475.  
  1476.     index = chartoindex(fnt,c);
  1477.     if(index<0) {
  1478.     fprintf(stderr,"Addcharmetrics bad poop\n");
  1479.     return;
  1480.     }
  1481.     cd = fnt->chars+index;
  1482.     cd->movex = movex;
  1483.     cd->movey = movey;
  1484. }
  1485.  
  1486. drawobjchar(fnt,c)
  1487. objfnt *fnt;
  1488. int c;
  1489. {
  1490.     chardesc *cd;
  1491.  
  1492.     cd = getchardesc(fnt,c);
  1493.     if(!cd)
  1494.     return 0;
  1495.     if(cd->data) {
  1496.     switch(fnt->type) {
  1497.         case TM_TYPE:
  1498.         tmesh_draw(cd->data);
  1499.         break;
  1500.         case PO_TYPE:
  1501.         if(dopoints)
  1502.             point_draw(cd->data,dopoints);
  1503.         else
  1504.             poly_draw(cd->data);
  1505.         break;
  1506.         case SP_TYPE:
  1507.         spline_draw(cd->data);
  1508.         break;
  1509.         default:
  1510.         fprintf(stderr,"drawobjchar: bad obj font type\n");
  1511.     }
  1512.     }
  1513.     translate((float)cd->movex,(float)cd->movey,0.0);
  1514.     return 1;
  1515. }
  1516.  
  1517. drawobjcharbbox(fnt,c)
  1518. objfnt *fnt;
  1519. int c;
  1520. {
  1521.     chardesc *cd;
  1522.  
  1523.     cd = getchardesc(fnt,c);
  1524.     if(!cd)
  1525.     return 0;
  1526.     if(cd->llx != NOBBOX) 
  1527.     drawrect((float)cd->llx,(float)cd->lly,(float)cd->urx,(float)cd->ury);
  1528.     return 1;
  1529. }
  1530.  
  1531. getcharadvance(fnt,c,dx,dy)
  1532. objfnt *fnt;
  1533. int c, *dx, *dy;
  1534. {
  1535.     int index;
  1536.     chardesc *cd;
  1537.  
  1538.     index = chartoindex(fnt,c);
  1539.     if(index<0) {
  1540.     *dx = 0;
  1541.     *dy = 0;
  1542.     return 0;
  1543.     } else {
  1544.     cd = fnt->chars+index;
  1545.     *dx = cd->movex;
  1546.     *dy = cd->movey;
  1547.     return 1;
  1548.     }
  1549. }
  1550.  
  1551. static float fontsize = 1.0;
  1552. static float xpos, ypos;
  1553. static int nfonts;
  1554. static char *names[40];
  1555. static objfnt *objfnts[40];
  1556. static objfnt *curfont;
  1557.  
  1558. fontsetsize(size)
  1559. float size;
  1560. {
  1561.     fontsize = size;
  1562. }
  1563.  
  1564. fontmoveto(x,y)
  1565. float x, y;
  1566. {
  1567.     xpos = x;
  1568.     ypos = y;
  1569. }
  1570.  
  1571. fontrmoveto(x,y)
  1572. float x, y;
  1573. {
  1574.     xpos += x;
  1575.     ypos += y;
  1576. }
  1577.  
  1578. fontptr(fnt)
  1579. objfnt *fnt;
  1580. {
  1581.     curfont = fnt;
  1582. }
  1583.  
  1584. objfnt *fontname(name)
  1585. char *name;
  1586. {
  1587.     objfnt *fnt;
  1588.     int i;
  1589.  
  1590.     for(i=0; i<nfonts; i++) {
  1591.     if(strcmp(name,names[i]) == 0) {
  1592.         curfont = objfnts[i];
  1593.         return curfont;
  1594.     }
  1595.     }
  1596.     if(nfonts==256) {
  1597.     fprintf(stderr,"fontname: too many fonts\n",name);
  1598.     return NULL;
  1599.     }
  1600.     fnt = readobjfnt(name);
  1601.     if(!fnt) {
  1602.     fprintf(stderr,"fontname: can't find font %s\n",name);
  1603.     return NULL;
  1604.     } else {
  1605.     objfnts[nfonts] = fnt;
  1606.     names[nfonts] = (char *)mymalloc(strlen(name)+1);
  1607.     bcopy(name,names[nfonts],strlen(name)+1);
  1608.     nfonts++;
  1609.     curfont = fnt;
  1610.     return curfont;
  1611.     }
  1612. }
  1613.  
  1614. fontpurge(name)
  1615. char *name;
  1616. {
  1617. int i, k;
  1618.  
  1619.     for(i=0; i<nfonts; i++) {
  1620.     if(strcmp(name,names[i]) == 0) {
  1621.         if (curfont == objfnts[i])    {
  1622.         if (nfonts > 0)
  1623.             curfont = objfnts[0];
  1624.         else 
  1625.             curfont = NULL;
  1626.         }
  1627.         free (objfnts[i]);        /* XXXX */
  1628.         free (names[i]);
  1629.         for (k = i; k < nfonts - 1; k++) {
  1630.         objfnts[k] = objfnts[k+1];
  1631.         names[k] = names[k+1];
  1632.         }
  1633.         nfonts--;
  1634.         return;
  1635.     }
  1636.     }
  1637.     fprintf (stderr, "fontfree: couldn't find font %s to delete!\n", name);
  1638. }
  1639.  
  1640. float fontstringwidth(str)
  1641. unsigned char *str;
  1642. {
  1643.     int width, w, dy;
  1644.  
  1645.     width = 0;
  1646.     while(*str) {
  1647.     getcharadvance(curfont,*str,&w,&dy); 
  1648.     str++;
  1649.     width += w;
  1650.     }
  1651.     return width*fontsize/curfont->scale;
  1652. }
  1653.  
  1654. fontshow(str)
  1655. unsigned char *str;
  1656. {
  1657.     int n, onechar;
  1658.  
  1659.     pushmatrix();
  1660.     translate(xpos,ypos,0.0);
  1661.     xpos += fontstringwidth(str);
  1662.     scale(fontsize/curfont->scale,fontsize/curfont->scale,0.0);
  1663.     n = 0;
  1664.     while(*str) {
  1665.     n += drawobjchar(curfont,*str); 
  1666.     str++;
  1667.     }
  1668.     popmatrix();
  1669.     return n;
  1670. }
  1671.  
  1672. bboxshow(str)
  1673. unsigned char *str;
  1674. {
  1675.     int n, onechar;
  1676.  
  1677.     pushmatrix();
  1678.     translate(xpos,ypos,0.0);
  1679.     xpos += fontstringwidth(str);
  1680.     scale(fontsize/curfont->scale,fontsize/curfont->scale,0.0);
  1681.     n = 0;
  1682.     while(*str) {
  1683.     n += drawobjcharbbox(curfont,*str); 
  1684.     str++;
  1685.     }
  1686.     popmatrix();
  1687.     return n;
  1688. }
  1689.  
  1690. char *asciiname(c)
  1691. char c;
  1692. {
  1693.     if((c>=MIN_ASCII) && (c<=MAX_ASCII)) 
  1694.     return charlist[c-MIN_ASCII].name+1;
  1695.     else 
  1696.     return 0;
  1697. }
  1698.  
  1699. hasvertdata(fnt,c)
  1700. objfnt *fnt;
  1701. int c;
  1702. {
  1703.     chardesc *cd;
  1704.  
  1705.     cd = getchardesc(fnt,c);
  1706.     if(cd->llx == NOBBOX)
  1707.     return 0;
  1708.     else
  1709.     return 1;
  1710. }
  1711.  
  1712. fontcentershow(str)
  1713. char *str;
  1714. {
  1715.     float width;
  1716.     
  1717.     width = fontstringwidth(str);
  1718.     fontrmoveto(-width/2.0,0.0);
  1719.     fontshow(str);
  1720. }
  1721.  
  1722. fakechar(fnt,c,width)
  1723. objfnt *fnt;
  1724. int c, width;
  1725. {
  1726.     short chardata[1];
  1727.  
  1728.     chardata[0] = PO_RET;
  1729.     addchardata(fnt,c,chardata,1);
  1730.     addcharmetrics(fnt,c,width,0);
  1731. }
  1732.  
  1733. mergefont(dest,src)
  1734. objfnt *dest, *src;
  1735. {
  1736.     int c;
  1737.     chardesc *dcd, *scd;
  1738.  
  1739.     for(c=dest->charmin; c<=dest->charmax; c++) {
  1740.     if(charexists(src,c)) {
  1741.         dcd = getchardesc(dest,c);
  1742.         scd = getchardesc(src,c);
  1743.         dcd->movex = scd->movex;
  1744.         dcd->movey = scd->movey;
  1745.         dcd->llx = scd->llx;
  1746.         dcd->lly = scd->lly;
  1747.         dcd->urx = scd->urx;
  1748.         dcd->ury = scd->ury;
  1749.         dcd->datalen = scd->datalen;
  1750.         dcd->data = (short *)mymalloc(dcd->datalen);
  1751.         bcopy(scd->data,dcd->data,dcd->datalen);
  1752.     }
  1753.     }
  1754. }
  1755.  
  1756. charexists(fnt,c)
  1757. objfnt *fnt;
  1758. int c;
  1759. {
  1760.     chardesc *cd;
  1761.  
  1762.     cd=getchardesc(fnt,c);
  1763.     if(!cd) 
  1764.     return 0;
  1765.     else if(cd->data)
  1766.        return 1;
  1767.     else
  1768.        return 0;
  1769. }
  1770.